package io.gitee.twoke.generator.spring;

import io.gitee.twoke.generator.engine.GenerateEngine;
import io.gitee.twoke.generator.engine.GenerateEngineConfiguration;
import io.gitee.twoke.generator.engine.GenerateEngines;
import io.gitee.twoke.generator.engine.impl.cfg.GenerateEngineConfigurationImpl;
import io.gitee.twoke.generator.engine.impl.cfg.StandaloneGenerateEngineConfiguration;
import io.gitee.twoke.generator.engine.impl.interceptor.CommandInterceptor;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

public class SpringGenerateEngineConfiguration
    extends GenerateEngineConfigurationImpl implements ApplicationContextAware {

    protected PlatformTransactionManager transactionManager;
    protected Integer transactionSynchronizationAdapterOrder = null;
    protected ApplicationContext applicationContext;

    @Override
    public GenerateEngine buildGenerateEngine() {
        GenerateEngine processEngine = super.buildGenerateEngine();
        GenerateEngines.setInitialized(true);
        return processEngine;
    }

    @Override
    public CommandInterceptor createTransactionInterceptor() {
        if (transactionManager == null) {
            throw new RuntimeException("transactionManager is required property for SpringProcessEngineConfiguration, use " +
                    StandaloneGenerateEngineConfiguration.class.getName() + " otherwise");
        }
        return new SpringTransactionInterceptor(transactionManager);
    }


    @Override
    public void initTransactionContextFactory() {
        if (transactionContextFactory == null && transactionManager != null) {
            transactionContextFactory = new SpringTransactionContextFactory(transactionManager, transactionSynchronizationAdapterOrder);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public GenerateEngineConfiguration setDataSource(DataSource dataSource) {
        if (dataSource instanceof TransactionAwareDataSourceProxy) {
            return super.setDataSource(dataSource);
        } else {
            // Wrap datasource in Transaction-aware proxy
            DataSource proxiedDataSource = new TransactionAwareDataSourceProxy(dataSource);
            return super.setDataSource(proxiedDataSource);
        }
    }

    public PlatformTransactionManager getTransactionManager() {
        return transactionManager;
    }

    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public void setTransactionSynchronizationAdapterOrder(Integer transactionSynchronizationAdapterOrder) {
        this.transactionSynchronizationAdapterOrder = transactionSynchronizationAdapterOrder;
    }

}
